package cn.com.franke.concurrency;

import com.google.common.util.concurrent.Monitor;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by liuzh on 2017/5/1.
 * 通过Monitor的Guard进行条件阻塞
 */
public class MonitorSample {
    private List<String> list = new ArrayList<String>();
    private static final int MAX_SIZE = 10;
    private Monitor monitor = new Monitor();

    private Monitor.Guard listBelowCapacity = new Monitor.Guard(monitor) {
        @Override
        public boolean isSatisfied() {
            return list.size() < MAX_SIZE;
        }
    };

    public void addToList(String item) throws InterruptedException {
        monitor.enterWhen(listBelowCapacity); //Guard(形如Condition)，不满足则阻塞，而且我们并没有在Guard进行任何通知操作
        try {
            list.add(item);
            System.out.println(list.size());
        } finally {
            monitor.leave();
        }
    }

    public boolean addToList1(String item) {
        boolean flag = false;
        if (monitor.enterIf(listBelowCapacity)) {
            try {
                list.add(item);
                System.out.println(list.size());
                flag = true;
            } finally {
                monitor.leave();
            }
        }
        return flag;
    }

    @Test
    public void test1() {
        try {
            for (int i = 0; i < 11; i++) {
                this.addToList("liu");//阻塞
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void test2() {
        try {
            for (int i = 0; i < 11; i++) {
                this.addToList1("liu");//非阻塞
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//    其他的Monitor访问方法：
//
//    Monitor.enter //进入Monitor块，将阻塞其他线程直到Monitor.leave
//    Monitor.tryEnter //尝试进入Monitor块，true表示可以进入, false表示不能，并且不会一直阻塞
//    Monitor.tryEnterIf //根据条件尝试进入Monitor块
//    这几个方法都有对应的超时设置版本。


}
